/*
 **
 ** Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
package com.android.packageinstaller;

import android.R.integer;
import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageUserState;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageParser;
import android.content.pm.VerificationParams;
import android.content.res.Resources;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AppSecurityPermissions;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;

/*
 * This activity is launched when a new application is installed via side loading
 * The package is first parsed and the user is notified of parse errors via a dialog.
 * If the package is successfully parsed, the user is notified to turn on the install unknown
 * applications setting. A memory check is made at this point and the user is notified of out
 * of memory conditions if any. If the package is already existing on the device, 
 * a confirmation dialog (to replace the existing package) is presented to the user.
 * Based on the user response the package is then installed by launching InstallAppConfirm
 * sub activity. All state transitions are handled in this activity
 */
public class PackageInstallerActivity extends Activity implements
		OnCancelListener, OnClickListener {
	private static final String TAG = "PackageInstaller";
	private Uri mPackageURI;
	private Uri mOriginatingURI;
	private Uri mReferrerURI;
	private int mOriginatingUid = VerificationParams.NO_UID;

	private boolean localLOGV = false;
	PackageManager mPm;
	PackageInfo mPkgInfo;
	ApplicationInfo mSourceInfo;

	// ApplicationInfo object primarily used for already existing applications
	private ApplicationInfo mAppInfo = null;
	
	CharSequence mLable = null; 

	// View for install progress
	View mInstallConfirm;
	// Buttons to indicate user acceptance
	private Button mOk;
	private Button mCancel;
	CaffeinatedScrollView mScrollView = null;
	
	private boolean mOkCanInstall = false;

	static final String PREFS_ALLOWED_SOURCES = "allowed_sources";

	// Dialog identifiers used in showDialog
	private static final int DLG_BASE = 0;
	private static final int DLG_UNKNOWN_APPS = DLG_BASE + 1;
	private static final int DLG_PACKAGE_ERROR = DLG_BASE + 2;
	private static final int DLG_OUT_OF_SPACE = DLG_BASE + 3;
	private static final int DLG_INSTALL_ERROR = DLG_BASE + 4;
	private static final int DLG_ALLOW_SOURCE = DLG_BASE + 5;

	/**
	 * This is a helper class that implements the management of tabs and all
	 * details of connecting a ViewPager with associated TabHost. It relies on a
	 * trick. Normally a tab host has a simple API for supplying a View or
	 * Intent that each tab will show. This is not sufficient for switching
	 * between pages. So instead we make the content part of the tab host 0dp
	 * high (it is not shown) and the TabsAdapter supplies its own dummy view to
	 * show as the tab content. It listens to changes in tabs, and takes care of
	 * switch to the correct paged in the ViewPager whenever the selected tab
	 * changes.
	 */
	public static class TabsAdapter extends PagerAdapter implements
			TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
		private final Context mContext;
		private final TabHost mTabHost;
		private final ViewPager mViewPager;
		private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
		private final Rect mTempRect = new Rect();

		static final class TabInfo {
			private final String tag;
			private final View view;

			TabInfo(String _tag, View _view) {
				tag = _tag;
				view = _view;
			}
		}

		static class DummyTabFactory implements TabHost.TabContentFactory {
			private final Context mContext;

			public DummyTabFactory(Context context) {
				mContext = context;
			}

			@Override
			public View createTabContent(String tag) {
				View v = new View(mContext);
				v.setMinimumWidth(0);
				v.setMinimumHeight(0);
				return v;
			}
		}

		public TabsAdapter(Activity activity, TabHost tabHost, ViewPager pager) {
			mContext = activity;
			mTabHost = tabHost;
			mViewPager = pager;
			mTabHost.setOnTabChangedListener(this);
			mViewPager.setAdapter(this);
			mViewPager.setOnPageChangeListener(this);
		}

		public void addTab(TabHost.TabSpec tabSpec, View view) {
			tabSpec.setContent(new DummyTabFactory(mContext));
			String tag = tabSpec.getTag();

			TabInfo info = new TabInfo(tag, view);
			mTabs.add(info);
			mTabHost.addTab(tabSpec);
			notifyDataSetChanged();
		}

		@Override
		public int getCount() {
			return mTabs.size();
		}

		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			View view = mTabs.get(position).view;
			container.addView(view);
			return view;
		}

		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView((View) object);
		}

		@Override
		public boolean isViewFromObject(View view, Object object) {
			return view == object;
		}

		@Override
		public void onTabChanged(String tabId) {
			int position = mTabHost.getCurrentTab();
			mViewPager.setCurrentItem(position);
		}

		@Override
		public void onPageScrolled(int position, float positionOffset,
				int positionOffsetPixels) {
		}

		@Override
		public void onPageSelected(int position) {
			// Unfortunately when TabHost changes the current tab, it kindly
			// also takes care of putting focus on it when not in touch mode.
			// The jerk.
			// This hack tries to prevent this from pulling focus out of our
			// ViewPager.
			TabWidget widget = mTabHost.getTabWidget();
			int oldFocusability = widget.getDescendantFocusability();
			widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
			mTabHost.setCurrentTab(position);
			widget.setDescendantFocusability(oldFocusability);

			// Scroll the current tab into visibility if needed.
			View tab = widget.getChildTabViewAt(position);
			mTempRect.set(tab.getLeft(), tab.getTop(), tab.getRight(),
					tab.getBottom());
			widget.requestRectangleOnScreen(mTempRect, false);

			// Make sure the scrollbars are visible for a moment after selection
			final View contentView = mTabs.get(position).view;
			if (contentView instanceof CaffeinatedScrollView) {
				((CaffeinatedScrollView) contentView).awakenScrollBars();
			}
		}

		@Override
		public void onPageScrollStateChanged(int state) {
		}
	}

	private void startInstallConfirm() {
		TabHost tabHost = (TabHost) findViewById(android.R.id.tabhost);
		tabHost.setup();
		tabHost.setVisibility(View.GONE);
		ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
		TabsAdapter adapter = new TabsAdapter(this, tabHost, viewPager);
		boolean permVisible = false;
		mScrollView = null;
		mOkCanInstall = false;
		int msg = 0;
		String msgString1 = null;
		String msgString2 = " ";
		int msgImage = 0;
		if (mPkgInfo != null) {

			AppSecurityPermissions perms = new AppSecurityPermissions(this,
					mPkgInfo);
			final int NP = perms
					.getPermissionCount(AppSecurityPermissions.WHICH_PERSONAL);
			final int ND = perms
					.getPermissionCount(AppSecurityPermissions.WHICH_DEVICE);
			if (mAppInfo != null) {
				msg = (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ? R.string.install_confirm_question_update_system
						: R.string.install_confirm_question_update;
				msgImage = R.drawable.install_question;
				if(mLable != null){
					msgString1 = getResources().getString(R.string.install_confirm_question_update1)+mLable+getResources().getString(R.string.install_confirm_question_update2);
				}else{
					msgString1 = getResources().getString(R.string.install_confirm_question_update1)+"此应用"+getResources().getString(R.string.install_confirm_question_update2);
				}
				msgString2 = getResources().getString(R.string.install_confirm_question_update3);
				mScrollView = new CaffeinatedScrollView(this);
				mScrollView.setFillViewport(true);
				if (perms.getPermissionCount(AppSecurityPermissions.WHICH_NEW) > 0) {
					permVisible = true;
					mScrollView
							.addView(perms
									.getPermissionsView(AppSecurityPermissions.WHICH_NEW));
				} else {
					LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
					TextView label = (TextView) inflater.inflate(
							R.layout.label, null);
					label.setText(R.string.no_new_perms);
					mScrollView.addView(label);
				}
				adapter.addTab(
						tabHost.newTabSpec("new").setIndicator(
								getText(R.string.newPerms)), mScrollView);
			} else {
				msgString2 = getResources().getString(R.string.install_confirm_question_update3);
				findViewById(R.id.tabscontainer).setVisibility(View.GONE);
				findViewById(R.id.divider).setVisibility(View.VISIBLE);
			}
			if (NP > 0 || ND > 0) {
				permVisible = true;
				LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				View root = inflater.inflate(R.layout.permissions_list, null);
				if (mScrollView == null) {
					mScrollView = (CaffeinatedScrollView) root
							.findViewById(R.id.scrollview);
				}
				if (NP > 0) {
					((ViewGroup) root.findViewById(R.id.privacylist))
							.addView(perms
									.getPermissionsView(AppSecurityPermissions.WHICH_PERSONAL));
				} else {
					root.findViewById(R.id.privacylist)
							.setVisibility(View.GONE);
				}
				if (ND > 0) {
					((ViewGroup) root.findViewById(R.id.devicelist))
							.addView(perms
									.getPermissionsView(AppSecurityPermissions.WHICH_DEVICE));
				} else {
					root.findViewById(R.id.devicelist).setVisibility(View.GONE);
				}
				adapter.addTab(
						tabHost.newTabSpec("all").setIndicator(
								getText(R.string.allPerms)), root);
			}
		}
		if (!permVisible) {
			if (mAppInfo != null) {
				msgString2 = getResources().getString(R.string.install_confirm_question_update3);	
			} else {
				// This is a new application with no permissions.
				msgString2 = getResources().getString(R.string.install_confirm_question_no_perms1);
			}
			tabHost.setVisibility(View.GONE);
			findViewById(R.id.filler).setVisibility(View.VISIBLE);
			findViewById(R.id.divider).setVisibility(View.GONE);
			mScrollView = null;
		}
		Log.d(TAG, "msgString : " + msgString1 + " mPkgInfo.applicationInfo 1: " + mPkgInfo.applicationInfo.name + mPkgInfo.packageName + "appTitle: " + mLable);
		Log.d(TAG, "mScrollView mOk.setText 11111");
		if(msgString1 != null){
			if(msgImage != 0){
				((ImageView)findViewById(R.id.install_image_view)).setImageResource(msgImage);	
			}
			((TextView) findViewById(R.id.install_confirm_question))
			.setText(msgString1);
			((TextView) findViewById(R.id.install_confirm_question_desc))
			.setText(msgString2);
			
		}else{
			if(msgImage != 0){
				((ImageView)findViewById(R.id.install_image_view)).setImageResource(msgImage);	
			}
			((TextView) findViewById(R.id.install_confirm_question_desc))
			.setText(msgString2);
		}

		mInstallConfirm.setVisibility(View.VISIBLE);
		mOk = (Button) findViewById(R.id.ok_button);
		mCancel = (Button) findViewById(R.id.cancel_button);
		mOk.setOnClickListener(this);
		mCancel.setOnClickListener(this);
		Log.d(TAG, "mScrollView mOk.setText 22222");

		mOk.setText(R.string.install);
		mOkCanInstall = true;
	}

	private void showDialogInner(int id) {
		// TODO better fix for this? Remove dialog so that it gets created again
		removeDialog(id);
		showDialog(id);
	}

	@Override
	public Dialog onCreateDialog(int id, Bundle bundle) {
		switch (id) {
		case DLG_UNKNOWN_APPS:
			return new AlertDialog.Builder(this)
					.setTitle(R.string.unknown_apps_dlg_title)
					.setMessage(R.string.unknown_apps_dlg_text)
					.setNegativeButton(R.string.cancel,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									Log.i(TAG,
											"Finishing off activity so that user can navigate to settings manually");
									finish();
								}
							})
					.setPositiveButton(R.string.settings,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									Log.i(TAG, "Launching settings");
									launchSettingsAppAndFinish();
								}
							}).setOnCancelListener(this).create();
		case DLG_PACKAGE_ERROR:
			return new AlertDialog.Builder(this)
					.setTitle(R.string.Parse_error_dlg_title)
					.setMessage(R.string.Parse_error_dlg_text)
					.setPositiveButton(R.string.ok,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									finish();
								}
							}).setOnCancelListener(this).create();
		case DLG_OUT_OF_SPACE:
			// Guaranteed not to be null. will default to package name if not
			// set by app
			CharSequence appTitle = mPm
					.getApplicationLabel(mPkgInfo.applicationInfo);
			String dlgText = getString(R.string.out_of_space_dlg_text,
					appTitle.toString());
			return new AlertDialog.Builder(this)
					.setTitle(R.string.out_of_space_dlg_title)
					.setMessage(dlgText)
					.setPositiveButton(R.string.manage_applications,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									// launch manage applications
									Intent intent = new Intent(
											"android.intent.action.MANAGE_PACKAGE_STORAGE");
									intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
									startActivity(intent);
									finish();
								}
							})
					.setNegativeButton(R.string.cancel,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									Log.i(TAG, "Canceling installation");
									finish();
								}
							}).setOnCancelListener(this).create();
		case DLG_INSTALL_ERROR:
			// Guaranteed not to be null. will default to package name if not
			// set by app
			CharSequence appTitle1 = mPm
					.getApplicationLabel(mPkgInfo.applicationInfo);
			String dlgText1 = getString(R.string.install_failed_msg,
					appTitle1.toString());
			return new AlertDialog.Builder(this)
					.setTitle(R.string.install_failed)
					.setNeutralButton(R.string.ok,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									finish();
								}
							}).setMessage(dlgText1).setOnCancelListener(this)
					.create();
		case DLG_ALLOW_SOURCE:
			CharSequence appTitle2 = mPm.getApplicationLabel(mSourceInfo);
			String dlgText2 = getString(R.string.allow_source_dlg_text,
					appTitle2.toString());
			return new AlertDialog.Builder(this)
					.setTitle(R.string.allow_source_dlg_title)
					.setMessage(dlgText2)
					.setNegativeButton(R.string.cancel,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									setResult(RESULT_CANCELED);
									finish();
								}
							})
					.setPositiveButton(R.string.ok,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									SharedPreferences prefs = getSharedPreferences(
											PREFS_ALLOWED_SOURCES,
											Context.MODE_PRIVATE);
									prefs.edit()
											.putBoolean(
													mSourceInfo.packageName,
													true).apply();
									startInstallConfirm();
								}
							}).setOnCancelListener(this).create();
		}
		return null;
	}

	private void launchSettingsAppAndFinish() {
		// Create an intent to launch SettingsTwo activity
		Intent launchSettingsIntent = new Intent(
				Settings.ACTION_SECURITY_SETTINGS);
		launchSettingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		startActivity(launchSettingsIntent);
		finish();
	}

	private boolean isInstallingUnknownAppsAllowed() {
		return Settings.Global.getInt(getContentResolver(),
				Settings.Global.INSTALL_NON_MARKET_APPS, 0) > 0;
	}

	private void initiateInstall() {
		String pkgName = mPkgInfo.packageName;
		// Check if there is already a package on the device with this name
		// but it has been renamed to something else.
		String[] oldName = mPm
				.canonicalToCurrentPackageNames(new String[] { pkgName });
		if (oldName != null && oldName.length > 0 && oldName[0] != null) {
			pkgName = oldName[0];
			mPkgInfo.packageName = pkgName;
			mPkgInfo.applicationInfo.packageName = pkgName;
		}
		// Check if package is already installed. display confirmation dialog if
		// replacing pkg
		try {
			// This is a little convoluted because we want to get all
			// uninstalled
			// apps, but this may include apps with just data, and if it is just
			// data we still want to count it as "installed".
			mAppInfo = mPm.getApplicationInfo(pkgName,
					PackageManager.GET_UNINSTALLED_PACKAGES);
			if ((mAppInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
				mAppInfo = null;
			}
		} catch (NameNotFoundException e) {
			mAppInfo = null;
		}
		startInstallConfirm();
	}

	void setPmResult(int pmResult) {
		Intent result = new Intent();
		result.putExtra(Intent.EXTRA_INSTALL_RESULT, pmResult);
		setResult(pmResult == PackageManager.INSTALL_SUCCEEDED ? RESULT_OK
				: RESULT_FIRST_USER, result);
	}

	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		// get intent information
		final Intent intent = getIntent();
		mPackageURI = intent.getData();
		mOriginatingURI = intent
				.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
		mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
		mPm = getPackageManager();

		final String scheme = mPackageURI.getScheme();
		if (scheme != null && !"file".equals(scheme)
				&& !"package".equals(scheme)) {
			Log.w(TAG, "Unsupported scheme " + scheme);
			setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
			return;
		}

		final PackageUtil.AppSnippet as;
		if ("package".equals(mPackageURI.getScheme())) {
			try {
				mPkgInfo = mPm.getPackageInfo(
						mPackageURI.getSchemeSpecificPart(),
						PackageManager.GET_PERMISSIONS
								| PackageManager.GET_UNINSTALLED_PACKAGES);
			} catch (NameNotFoundException e) {
			}
			if (mPkgInfo == null) {
				Log.w(TAG, "Requested package " + mPackageURI.getScheme()
						+ " not available. Discontinuing installation");
				showDialogInner(DLG_PACKAGE_ERROR);
				setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
				return;
			}
			as = new PackageUtil.AppSnippet(
					mPm.getApplicationLabel(mPkgInfo.applicationInfo),
					mPm.getApplicationIcon(mPkgInfo.applicationInfo));
		} else {
			final File sourceFile = new File(mPackageURI.getPath());
			PackageParser.Package parsed = PackageUtil
					.getPackageInfo(sourceFile);
			// Check for parse errors
			if (parsed == null) {
				Log.w(TAG,
						"Parse error when parsing manifest. Discontinuing installation");
				showDialogInner(DLG_PACKAGE_ERROR);
				setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
				return;
			}
			mPkgInfo = PackageParser.generatePackageInfo(parsed, null,
					PackageManager.GET_PERMISSIONS, 0, 0, null,
					new PackageUserState());
			as = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo,
					sourceFile);
		}
		
		if(as != null){
			mLable = as.label;
		}

		//add by wz dxj 
		//modify dzg 2017-08-15 增加白名单策略
		PackageParser.Package packages = null;
		if (packages == null) {
			File sourceFile = new File(mPackageURI.getPath());
			packages = PackageUtil.getPackageInfo(sourceFile);
			if (packages != null) {
				PackageInfo packageInfo = null;
				try {
					packageInfo = mPm.getPackageInfo(packages.packageName.toString(), 0);
				}catch(NameNotFoundException e){
					;
				}				
				try{
					if (packageInfo == null) {
						if (!WZCheckAllowInstallAppPackage(packages.packageName.toString())){
							//不允许安装
							showNOtAllowDialog();
							return;
						}
					}					
					//允许安装
					{						
						// set view
						setContentView(R.layout.install_start);
						mInstallConfirm = findViewById(R.id.install_confirm_panel);
						mInstallConfirm.setVisibility(View.INVISIBLE);
						PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);

						mOriginatingUid = getOriginatingUid(intent);

						// Deal with install source.
						String callerPackage = getCallingPackage();
						if (callerPackage != null
								&& intent.getBooleanExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE,
										false)) {
								mSourceInfo = mPm.getApplicationInfo(callerPackage, 0);
								if (mSourceInfo != null) {
									if ((mSourceInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
										// System apps don't need to be approved.
										initiateInstall();
										return;
									}
								}
						}
						initiateInstall();
					}
					
				} catch (Exception e) {
					e.printStackTrace();
					showNOtAllowDialog();
				}
			}
		}
	}

	private void showNOtAllowDialog() {
		new CustomDialog.Builder(PackageInstallerActivity.this)
		.setTitle(R.string.errot_title)
		.setMessage(R.string.errot_manage)
		.setPositiveButton(
				getResources().getString(
						R.string.errot_no),
				new DialogInterface.OnClickListener() {
					public void onClick(
							DialogInterface arg0,
							int arg1) {
						PackageInstallerActivity.this
								.finish();
					}
				})
		.setNegativeButton(R.string.errot_ok,
				new android.content.DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				try {
					Intent intent1 = new Intent();
					//参数是包名，类全限定名，注意直接用类名不行
					ComponentName cn = new ComponentName("com.android.launcher",
					        "com.android.launcher.ui.activity.AppManagerActivity");
					intent1.setComponent(cn);
					startActivity(intent1);
				} catch (Exception e) {
					e.printStackTrace();
				}
				PackageInstallerActivity.this
						.finish();
				dialog.dismiss();
			}
		}).create().show();
	}

	/**
	 * 获得某个应用程序包的主Activity
	 * 
	 * @param ctx
	 * @return
	 */
	public static String getLunchActivity(Context ctx,String packageName) {

		PackageManager pm = ctx.getPackageManager();

		String className = null;
		try {
			Intent it = pm.getLaunchIntentForPackage(packageName);
			className = it.getComponent().getClassName();
			System.out.println(className);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return className;
	}
	
	/** Get the ApplicationInfo for the calling package, if available */
	private ApplicationInfo getSourceInfo() {
		String callingPackage = getCallingPackage();
		if (callingPackage != null) {
			try {
				return mPm.getApplicationInfo(callingPackage, 0);
			} catch (NameNotFoundException ex) {
				// ignore
			}
		}
		return null;
	}

	/**
	 * Get the originating uid if possible, or VerificationParams.NO_UID if not
	 * available
	 */
	private int getOriginatingUid(Intent intent) {
		// The originating uid from the intent. We only trust/use this if it
		// comes from a
		// system application
		int uidFromIntent = intent.getIntExtra(Intent.EXTRA_ORIGINATING_UID,
				VerificationParams.NO_UID);

		// Get the source info from the calling package, if available. This will
		// be the
		// definitive calling package, but it only works if the intent was
		// started using
		// startActivityForResult,
		ApplicationInfo sourceInfo = getSourceInfo();
		if (sourceInfo != null) {
			if (uidFromIntent != VerificationParams.NO_UID
					&& (mSourceInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
				return uidFromIntent;

			}
			// We either didn't get a uid in the intent, or we don't trust it.
			// Use the
			// uid of the calling package instead.
			return sourceInfo.uid;
		}

		// We couldn't get the specific calling package. Let's get the uid
		// instead
		int callingUid;
		try {
			callingUid = ActivityManagerNative.getDefault().getLaunchedFromUid(
					getActivityToken());
		} catch (android.os.RemoteException ex) {
			Log.w(TAG, "Could not determine the launching uid.");
			// nothing else we can do
			return VerificationParams.NO_UID;
		}

		// If we got a uid from the intent, we need to verify that the caller is
		// a
		// system package before we use it
		if (uidFromIntent != VerificationParams.NO_UID) {
			String[] callingPackages = mPm.getPackagesForUid(callingUid);
			if (callingPackages != null) {
				for (String packageName : callingPackages) {
					try {
						ApplicationInfo applicationInfo = mPm
								.getApplicationInfo(packageName, 0);

						if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
							return uidFromIntent;
						}
					} catch (NameNotFoundException ex) {
						// ignore it, and try the next package
					}
				}
			}
		}
		// We either didn't get a uid from the intent, or we don't trust it. Use
		// the
		// calling uid instead.
		return callingUid;
	}

	// Generic handling when pressing back key
	public void onCancel(DialogInterface dialog) {
		finish();
	}

	public void onClick(View v) {
		if (v == mOk) {
			if (mOkCanInstall || mScrollView == null) {
				// Start subactivity to actually install the application
				Intent newIntent = new Intent();
				newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
						mPkgInfo.applicationInfo);
				newIntent.setData(mPackageURI);
				newIntent.setClass(this, InstallAppProgress.class);
				String installerPackageName = getIntent().getStringExtra(
						Intent.EXTRA_INSTALLER_PACKAGE_NAME);
				if (mOriginatingURI != null) {
					newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI,
							mOriginatingURI);
				}
				if (mReferrerURI != null) {
					newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
				}
				if (mOriginatingUid != VerificationParams.NO_UID) {
					newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID,
							mOriginatingUid);
				}
				if (installerPackageName != null) {
					newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
							installerPackageName);
				}
				if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT,
						false)) {
					newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
					newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
				}
				if (localLOGV)
					Log.i(TAG, "downloaded app uri=" + mPackageURI);
				startActivity(newIntent);
				finish();
			} else {
				mScrollView.pageScroll(View.FOCUS_DOWN);
			}
		} else if (v == mCancel) {
			// Cancel and finish
			setResult(RESULT_CANCELED);
			finish();
		}
	}
	
	
	/**
	 * 检测应用是否允许安装，使用语音接口确认
	 * dzg wz
	 * 2017-08-15 
	 * @param packagename
	 * @return
	 */
	private static boolean WZCheckAllowInstallAppPackage(String packagename){
		try{
			Class<?> WZVoiceControlServiceManagerClass = Class.forName("android.os.WZVoiceControlServiceManager");
			Method takeInjectNotAllowUrls = WZVoiceControlServiceManagerClass.getDeclaredMethod("takeInjectNotAllowUrls");
			String r = (String)takeInjectNotAllowUrls.invoke(null);
			if (r==null){
				//异常
				return false;//不允许
			}else if (r.equals("none")){
				//不需要
				return false;//不允许
			}else if (r.indexOf("@" + packagename + ";") > -1){
				//支持
				return true;
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return false;
	}
}
